Skip to content

Theme Development

Themes are a collection of page templates, assets (CSS, JS, etc) and a metadata file. They should use responsive design and be easily edited and viewed. Providing a variety of color schemes is recommended for users to choose from when building their site.

Folder Structure

This is the folder structure for a standard theme. The root folder shown below should be placed in [sitewriter app]/public/themes. Bold denotes a folder, italic denotes required.

  • Theme Name
    • theme.json
    • contact.php
    • default.php
    • 404.php
    • preview.png
    • colors
      • default
      • green
      • etc

If preview.png is present, it will be displayed to the user in the theme picker.

Metadata File

The metadata file is required for SiteWriter to recognize the theme. It must be saved as theme.json in the root folder of the theme.

It contains the theme name, singlepage flag, list of page templates, and list of theme colors.

singlepage is a flag that tells SiteWriter if the theme is designed for a single-page website. If it is set to true, page creation will be disabled and the site will only have a single page.

templates is a list of page templates. A template with an ID of default is required. The template ID is the name of the template file without the .php extension. For example, SiteWriter loads home.php to show a page with the home template.

colors is a list of color schemes for the theme. The color ID is the name of the folder where the color-specific assets are stored. A color of default is required. If the chosen color is green, the color-specific assets should be placed in colors/green in the theme folder.

Sample theme.json

{
    "name": "My Theme",
    "singlepage": false,
    "templates": {
        "default": {
            "title": "Default",
            "description": "A regular page."
        },
        "home": {
            "title": "Home",
            "description": "A homepage."
        },
        "contact": {
            "title": "Contact",
            "description": "A contact page."
        },
    },
    "colors": {
        "default": {
            "title": "Default",
            "description": "Blue color theme"
        },
        "green": {
            "title": "Green",
            "description": "Green color theme"
        }
    }
}

Templates

default.php

default.php is the default template file for a normal page in your theme. It is a standard PHP script containing HTML markup. It should never be loaded directly by a web browser, so you can safely assume theme functions and other SiteWriter theme utilities to be present.

404.php

As the name implies, this template is loaded to handle 404 errors. It is not user-selectable as a page template. It should not contain any user-editable fields, as there is currently no way for a user to edit site error pages.

contact.php

It is highly recommended to have a contact form template included in your theme. It should contain a standard form that POSTs to contact.php with the fields name, email, and message.

Template Requirements and Considerations

Do not use the optional <html>, <head>, and <body> tags for your template HTML. The editor relies on being able to append code to the document and have it still work normally.

Do include FontAwesome 5 in your theme. The SiteWriter editor allows the user to pick icons from the FontAwesome Free icon set to enhance their content. Use get_fontawesome_js() or get_fontawesome_css() instead of including FontAwesome in your theme. It saves space and ensures that all themes have the latest version of FontAwesome.

Do include company info (business name, phone number, address, and email), social media links (Facebook, Twitter, YouTube, Mastodon, etc), and footer links in the theme. These can be setup in the sitewide settings, and users will expect themes to make use of this information. See the Code Snippets section below for examples of this.

Do include <?php get_header(); ?> and <?php get_footer(); ?> snippets in your templates. They are used to inject additional content into the template, such as third-party analytics code.

Do copy code from the Bootstrap theme included with SiteWriter.

Common Component Names

To make theme transitions as seamless as possible, try to use the same component names as other themes for equivalent components.

  • Page subtitle: lead, plain text
  • Page content: content, rich text
  • Page banner (not page title): banner-title, plain text
  • Content cards: cardrow-$i, rich text (where $i is a number between 1 and 3)
  • Action buttons above the fold: banner-btn-$i, complex component with icon, link, and text (where $i is 1 or 2)
  • Contact form submit button: submit-btn, complex component with icon and text

Consult the included Bootstrap and Verti themes for example usage of these common components.

Example Template

Below is a minimal functional default template that fulfills the above requirements.

<!DOCTYPE html>
<meta charset=`utf-8`>
<title><?php get_site_name(); ?></title>
<script defer src="<?php get_fontawesome_js(); ?>"></script>
<?php get_header(); ?>
<!-- Navbar -->
<ul>
    <?php get_navigation(); ?>
</ul>
<h1><?php get_page_title(); ?></h1>
<h2>
    <div class="sw-text" data-component="lead">
        <?php get_component("lead"); ?>
    </div>
</h2>
<div class="sw-editable" data-component="content">
    <?php get_page_content(); ?>
</div>
<footer>
    <!-- Social Media -->
    <ul>
        <?php
        $social = get_socialmedia_urls();
        foreach ($social as $s) {
            ?>
            <a href="<?php echo $s['url']; ?>">
                <i class="<?php echo $s['icon']; ?> fa-fw"></i>
                <span><?php echo $s['name']; ?></span>
            </a>
            <?php
        }
        ?>
    </ul>
</footer>

Code Snippets

Components

Plain Text

<p class="sw-text" data-component="lead">
  <?php get_component("lead"); ?>
</p>

HTML

<div class="sw-editable" data-component="component-name">
  <?php get_component("component-name"); ?>
</div>

Complex

<?php
if (!is_complex_empty("complex-component-name")) {
    $comp = get_complex_component("complex-component-name", null, ['icon', 'image', 'link', 'text']);
    $icon = $comp['icon'];
    $image = $comp['image'];
    $link = $comp['link'];
    $text = $comp['text'];
?>
    <a href="<?php get_url_or_slug($link); ?>" class="sw-complex"
        data-json="<?php echo get_escaped_json($btn); ?>"
        data-component="complex-component-name" >

        <i class="<?php echo $icon; ?>"></i>
        <?php echo $text; ?>
        <img src="<?php get_file_url($image); ?>" />
    </a>
<?php } ?>

Useful Samples

<?php
$social = get_socialmedia_urls();
foreach ($social as $s) {
    ?>
    <li>
        <a href="<?php echo $s['url']; ?>">
            <i class="<?php echo $s['icon']; ?>"></i>
            <?php echo $s['name']; ?>
        </a>
    </li>
    <?php
}
?>

Contact Information

<?php
format_special(
    get_setting("address"),
    SPECIAL_TYPE_ADDRESS,
    '<p><b>Address:</b> <a href="[[CONTENT]]">[[TITLE]]</a></p>'
);
format_special(
    get_setting("email"),
    SPECIAL_TYPE_EMAIL,
    '<p><b>Email:</b> <a href="[[CONTENT]]">[[TITLE]]</a></p>'
);
format_special(
    get_setting("phone"),
    SPECIAL_TYPE_PHONE,
    '<p><b>Phone:</b> <a href="[[CONTENT]]">[[TITLE]]</a></p>'
);
?>
<ul>
    <?php
    $links = get_footer_urls();
    foreach ($links as $l) {
    ?>
    <li>
        <a href="<?php get_url_or_slug($l['link']); ?>">
            <i class="fas fa-arrow-right"></i> <?php echo $l['title']; ?>
        </a>
    </li>
    <?php } ?>
</ul>

Theme Functions

function get_site_name($echo = true)

Get the name of the website.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_site_url($echo = true)

Get the URL of the website.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_page_title($echo = true)

Get the page title.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_page_clean_title($echo = true)

Get the page title stripped of any HTML.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_page_slug($echo = true)

Get the page slug for the current page.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_page_clean_url($echo = true, $slug = null)

Get a valid minimal URL for a page.

  • Parameters:
  • $echoboolean — default true
  • $slugstring — page slug, or null for current
  • Returns: string

function get_page_url($echo = true, $slug = null)

Get a valid URL for a page.

  • Parameters:
  • $echoboolean — default true
  • $slugstring — page slug, or null for current
  • Returns: string

function get_component($name, $context = null, $echo = true, $default = "")

Echoes or returns the content of a component.

  • Parameters:
  • $namestring — component name
  • $contextstring — page slug, or null for current
  • $echoboolean — default true
  • $defaultstring — The content to return if the component is empty
  • Returns: string

function is_component_empty($name, $context = null)

Check if a component is empty of content.

  • Parameters:
  • $namestring — component name
  • $contextstring — page slug, or null for current
  • Returns: boolean

function get_complex_component($name, $context = null, $include = [])

Return the data for a complex component (icon, link, text, image, etc)

  • Parameters:
  • $namestring — component name
  • $contextstring — page slug, or null for current
  • $includearray — list of properties to include in the output
  • Returns: array

function is_complex_empty($name, $context = null)

Check if the specified complex component is empty.

  • Parameters:
  • $namestring
  • $contextstring — page slug
  • Returns: boolean

function get_escaped_json($json, $echo = true)

Convert a variable into encoded JSON for safe inclusion in an element property.

  • Parameters:
  • $json — or array to convert to JSON
  • $echoboolean — default true
  • Returns: string

function get_url_or_slug($str, $echo = true)

Detects if a string is a URL or a page slug, and returns something usable for href

  • Parameters:
  • $strstring
  • $echoboolean
  • Returns: string

function get_file_url($file, $echo = true)

Get a valid URL for a given file path. Detects if the file is uploaded via SiteWriter and acts accordingly.

  • Parameters:
  • $filestring
  • $echoboolean
  • Returns: string

function get_page_content($slug = null)

Shortcut for get_component("content").

  • Parameters: $slugstring — Get the content for the passed page instead of the current.

function get_header()

Echoes invisible page header content.

Echoes invisible page footer content.

function get_setting($key, $echo = false)

Return or echo the value of the given site setting key, or an empty string if unset.

  • Parameters:
  • $keystring
  • $echoboolean — default false
  • Returns: string

function get_theme_url($echo = true)

Get the URL path for the theme folder, without trailing slash.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_theme_color_url($echo = true)

Get the URL base for the selected theme color asset folder, without trailing slash.

  • Parameters: $echoboolean — default true
  • Returns: string

function get_navigation($currentpage = null, $classPrefix = "", $liclass = "", $currentclass = "current", $linkclass = "", $currentlinkclass = "active")

Get the page navigation as a string containing a series of

  • elements.

    Format:
    Current page:

    <li class="$classPrefix$slug $liclass $currentclass">
        <a class="$linkclass $currentlinkclass" href="url">
            Link Text
        </a>
    </li>
    

    Other pages:

    <li class="$classPrefix$slug $liclass">
        <a class="$linkclass" href="url">
            Link Text
        </a>
    </li>
    
    • Parameters:
    • $currentpagestring — The page slug to use for context, or null for current.
    • $classPrefixstring
    • $liclassstring
    • $currentclassstring — default "current"
    • $linkclassstring
    • $currentlinkclassstring — default "active"

    function output_conditional($content, $var)

    Replace "[[VAR]]" with the contents of $var and echo $content, but only if $var isn't empty.

    • Parameters:
    • $contentstring
    • $varstring

    function get_fontawesome_js($echo = true)

    Echos or returns a URL for the FontAwesome 5 JavaScript.

    • Parameters: $echoboolean — default true
    • Returns: string

    function get_fontawesome_css($echo = true)

    Echos or returns a URL for the FontAwesome 5 CSS WebFont.

    • Parameters: $echoboolean — default true
    • Returns: string

    Return an array [[title, link], [title, link]] of links for the page footer

    function get_socialmedia_urls()

    Returns an array of social media URLs, with FontAwesome icon classes and labels.

    • Returns: array — [["icon", "name", "url"]]

    function format_special($text, $type = SPECIAL_TYPE_NONE, $template = "", $title = null, $echo = true, $conditional = true)

    Take $text, format it according to $type, replace [[CONTENT]] in $template with it, and replace [[TITLE]] with $title (or the unchanged $text if $title is null)

    $type may be one of the following:

    • SPECIAL_TYPE_PHONE: tel:1234567890
    • SPECIAL_TYPE_EMAIL: mailto:[email protected]
    • SPECIAL_TYPE_LINEBREAKS: Replaces \n with <br />\n
    • SPECIAL_TYPE_ADDRESS: Creates a link to open Google Maps, and runs LINEBREAKS on $title
    • SPECIAL_TYPE_NONE: Does no text manipulation.

    • Parameters:
    • $textstring
    • $typeint
    • $templatestring
    • $titlestring
    • $echoboolean — default true
    • $conditionalboolean — Act as output_conditional() and not return anything if $text is empty
    • Returns: string